; joymouse.asm
; Mouse emulation with joystick
;

	.export handle_joymouse
	
	.export init_joy

	.include "common.inc"
	.include "mouse.inc"
	.include "screen.inc"
	.include "config.inc"

	.segment "RODATA"
	
accel_tbl:	.byte 1, 1, 1, 1, 2, 2, 2, 3

	.segment "ZEROPAGE"

joy_dxhi:	.res 1
joy_dyhi:	.res 1

	.segment "DATA"
	
joy_dx:		.byte 0
joy_dy:		.byte 0

joy_btn:	.byte 0
sig:		.byte 0
last_sig:	.byte 0
cur_acc:	.byte 0
new_x:		.word 0
new_y:		.word 0

	.segment "JMPTABLE" 

joyptr:		.word read_joy0

	.segment "BOOT"
	
	MAX_PORTS = 3

rplo:		.byte <read_joy0, <read_joy1, <read_joy2
rphi:		.byte >read_joy0, >read_joy1, >read_joy2
	
init_joy:	ldx #CONFIG_MOUSE_PORT
			jsr get_config
			cmp #MAX_PORTS
			bcs @fin
			tax
			beq @internal
			lda VIA1_BASE+2		; Protovision set-up
			ora #$80
			sta VIA1_BASE+2
@internal:	lda rplo, x
			sta joyptr
			lda rphi, x
			sta joyptr+1
@fin:		rts

	.segment "CODE"

;
;	Reads joystick port 0 (internal)
;
read_joy0:	; check switch states
			lda VIA1_BASE+1
			lsr
			lsr
			lsr
			bcs @no_up
			dec joy_dy		; move up
@no_up:		lsr
			bcs @no_down
			inc joy_dy		; move down
@no_down:	lsr
			bcs @no_left
			dec joy_dx		; move left
@no_left:	; check button
			lsr	
			lda #0
			rol
			eor #1
			sta joy_btn 
			; right?
			ldx VIA2_BASE+2
			lda #%01111111
			sta VIA2_BASE+2
			lda VIA2_BASE+0
			stx VIA2_BASE+2
			asl
			bcs @no_right
			inc joy_dx		; move right
			; extend signs to 16-bit
@no_right:	rts

;
;	Reads joystick port 1 or 2 (protovision adapter)
;
read_joy1:	lda #$80
			.byte $2C ; BIT ABS
read_joy2:	lda #0
			sta VIA1_BASE+0
@readin:	lda VIA1_BASE+0
			cmp VIA1_BASE+0
			bne @readin
			lsr
			bcs @nup
			dec joy_dy		; move up
@nup:		lsr
			bcs @ndn				
			inc joy_dy		; move down
@ndn:		lsr
			bcs @nleft
			dec joy_dx		; move left
@nleft:		lsr
			bcs @nright
			inc joy_dx		; move right
@nright:	eor #3
			and #3
			beq @nbutton
			lda #1
			.byte $2C ; BIT ABS
@nbutton:
			lda #0		
			sta joy_btn 

			rts
;
;	Reads active joystick port
;

read_joy:	jmp (joyptr)

;
;	Read joystick/mouse and calc new mouse position
;

handle_joymouse:
			jsr read_joy
			lda #$FF		; extend sign (dx)
			ldx #0
			bit joy_dx
			bpl @pos_dx
			sta joy_dxhi
			.byte $2C		; BIT abs
@pos_dx:	stx joy_dxhi
			bit joy_dy		; extend sign (dy)
			bpl @pos_dy
			sta joy_dyhi
			.byte $2C		; BIT abs
@pos_dy:	stx joy_dyhi
			; check acceleration (pre: X = 0)
			lda joy_dx
			and #3
			asl
			asl
			sta sig
			lda joy_dy
			and #3
			ora sig
			bne @doacc
			stx last_sig
			beq @dnacc
@doacc:		cmp last_sig
			sta last_sig
			beq @incacc
			ldx #0
			stx cur_acc
			beq @dnacc			
@incacc:	ldx cur_acc
			cpx #7
			bcs @dnacc
			inx
			stx cur_acc
@dnacc:		; calc new position (w/ acceleration)
			ldy accel_tbl, x
			lda #0
			sta new_x+1
			sta new_y+1
			lda mousex
			sta new_x
			lda mousey
			sta new_y
@incloop:	clc
			lda new_x
			adc joy_dx
			sta new_x
			lda new_x+1
			adc joy_dxhi
			sta new_x+1
			clc
			lda new_y
			adc joy_dy
			sta new_y
			lda new_y+1
			adc joy_dyhi
			sta new_y+1
			dey
			bne @incloop
			; set new position to X/Y
			ldx new_x
			ldy new_y
			; trunk X to 0..MAX_WIDTH-1
			lda #$FF
			bit new_x+1
			beq @xbyte
			bpl @toxmax
			ldx #0
@xbyte:		cpx scr_dim_x
			bcc @xinrng
@toxmax:	ldx scr_dim_x
			dex
@xinrng:	; trunk Y to 0..MAX_HEIGHT-1
			bit new_y+1
			beq @ybyte
			bpl @toymax
			ldy #0
@ybyte:		cpy scr_dim_y
			bcc @yinrng
@toymax:	ldy scr_dim_y
			dey
@yinrng:	; move mouse
			lda #0
			sta joy_dx
			sta joy_dy
			lda joy_btn
			jmp move_mouse
